' http://stackoverflow.com/questions/808736/set-system-time-zone-from-net
Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Imports System.Globalization
Imports MefTZAddin.interop.types

Namespace interop

    Public Module DynamicTimeZoneInterop
        <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Private Function GetDynamicTimeZoneInformation(ByRef lpTimeZoneInformation As DynamicTimeZoneInformation) As Integer
        End Function

        <DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
        Private Function SetDynamicTimeZoneInformation(<[In]()> ByRef lpTimeZoneInformation As DynamicTimeZoneInformation) As Boolean
        End Function

        Public Sub SetDynamicTimeZone(ByVal dtzi As DynamicTimeZoneInformation)
            ' Setting timezone is filtered from token by default
            AdjustPrivileges.SetTokenPrivilege(AdjustPrivileges.SE_TIME_ZONE_NAME)
            Win32.CheckWin32Error()

            Try
                ' Set local system timezone
                If SetDynamicTimeZoneInformation(dtzi) Then
                    Win32.CheckWin32Error()
                Else
                    ' TODO: Figure out how to update local settings since refreshing doesn't actually work...
                    SendMessageInterop.BroadcastSettingsChange()
                    CultureInfo.CurrentCulture.ClearCachedData()
                    TimeZoneInfo.ClearCachedData()
                End If
            Finally
                ' Setting timezone is filtered from token by default
                AdjustPrivileges.UnsetTokenPrivilege(AdjustPrivileges.SE_TIME_ZONE_NAME)
                Win32.CheckWin32Error()
            End Try
        End Sub

        Public Sub SetDynamicTimeZone(ByVal tzi As TimeZoneInfo)
            SetDynamicTimeZone(tzi.ToDynamicTimeZoneInformation())
        End Sub

        Public Function GetDynamicTimeZone() As DynamicTimeZoneInformation
            Dim dtzi As DynamicTimeZoneInformation = Nothing

            Dim currentTimeZone As Integer = GetDynamicTimeZoneInformation(dtzi)

            Win32.CheckWin32Error()

            Return dtzi
        End Function

        <System.Runtime.CompilerServices.Extension()> _
        Public Function ToDynamicTimeZoneInformation(ByVal tzi As TimeZoneInfo) As DynamicTimeZoneInformation
            Dim cpy As New DynamicTimeZoneInformation()
            cpy.bias = CInt(tzi.BaseUtcOffset.TotalMinutes)

            Dim rules As TimeZoneInfo.AdjustmentRule() = tzi.GetAdjustmentRules()

            If tzi.SupportsDaylightSavingTime AndAlso rules.Length > 0 Then
                cpy.daylightName = tzi.DaylightName
                cpy.daylightBias = CInt(rules(0).DaylightDelta.TotalMinutes)
                cpy.dynamicDaylightTimeDisabled = False

                For Each rule In rules
                    If DateTime.Now >= rule.DateStart AndAlso DateTime.Now <= rule.DateEnd Then
                        cpy.daylightDate = rule.DaylightTransitionStart.ToSystemTime()
                        cpy.standardDate = rule.DaylightTransitionEnd.ToSystemTime()
                        Exit For
                    End If
                Next
                cpy.daylightDate = rules(0).DateStart.ToSystemTime()
            Else
                cpy.daylightName = ""
                cpy.dynamicDaylightTimeDisabled = True
            End If

            cpy.standardName = tzi.StandardName
            cpy.timeZoneKeyName = tzi.StandardName

            Return cpy
        End Function
    End Module
End Namespace
